package s_005_Bean_Circular_Dependency;

import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import java.util.Arrays;

/**
 * 循环依赖
 * https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-dependency-resolution
 * https://blog.csdn.net/f641385712/article/details/92801300
 */
@ComponentScan // 默认当前类所在包路径
public class CircularDependency {
    /**
     * 三级缓存
     *
     * @see DefaultSingletonBeanRegistry
     * 一级缓存，单例对象的缓存：bean名称-bean实例，单例池
     * singletonObjects
     * 二级缓存，早期的单例对象的高速缓存：bean名称-bean实例
     * 表示 Bean 的生命周期还没走完（Bean 的属性还未填充）就把这个 Bean 存入该缓存中
     * 也就是实例化但未初始化的 bean 放入该缓存里
     * earlySingletonObjects
     * 三级缓存，单例工厂的高速缓存：bean 名称-ObjectFactory
     * 表示存放生成 bean 的工厂
     * singletonFactories
     * <p>
     * @see AbstractAutowireCapableBeanFactory
     * 去容器中拿 Bean，有则直接返回
     * getSingleton
     * 没有该 Bean 则创建
     * doCreateBean
     * Bean 创建过程中的属性填充
     * populateBean
     * Bean 彻底创建完成则添加进 singletonObjects
     * addSingleton
     * <p>
     * 过程
     * 1、A 创建过程中需要 B，于是 A 将自己放到三级缓里面，去实例化 B
     * 2、B 实例化的时候发现需要 A，于是 B 先查一级缓存，没有，再查二级缓存，还是没有，再查三级缓存，
     * 找到了 A，然后把三级缓存里面的这个 A 放到二级缓存里面，并删除三级缓存里面的 A
     * 3、B 顺利初始化完毕，将自己放到一级缓存里面（此时 B 里面的 A 依然是创建中状态），然后回来接着创建 A，
     * 此时 B 已经创建结束，A 直接从一级缓存里面拿到 B，然后 A 完成创建，并将 A 自己放到一级缓存里面。
     */
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(CircularDependency.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        Arrays.stream(beanDefinitionNames).forEach(System.out::println);
    }
}